package com.irdstudio.efp.nls.service.impl;

import com.irdstudio.basic.framework.core.constant.BaseConstant;
import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.basic.framework.core.util.DateUtility;
import com.irdstudio.efp.basic.framework.mq.client.producer.MQProducerMessageClient;
import com.irdstudio.efp.console.common.ConsoleEnums;
import com.irdstudio.efp.console.common.PrdStatEnums;
import com.irdstudio.efp.console.service.facade.PrdInfoService;
import com.irdstudio.efp.console.service.facade.PrdSoltRuleService;
import com.irdstudio.efp.console.service.facade.SCfgParamService;
import com.irdstudio.efp.console.service.vo.PrdInfoVO;
import com.irdstudio.efp.console.service.vo.PrdSoltRuleVO;
import com.irdstudio.efp.console.service.vo.SCfgParamVO;
import com.irdstudio.efp.cus.service.facade.CusWhiteListTecService;
import com.irdstudio.efp.cus.service.vo.CusWhiteListTecVO;
import com.irdstudio.efp.esb.common.constant.MsLoanConstant;
import com.irdstudio.efp.esb.service.facade.MsLoanService;
import com.irdstudio.efp.loan.service.facade.AccLoanService;
import com.irdstudio.efp.loan.service.vo.AccLoanVO;
import com.irdstudio.efp.nls.common.constant.PrdAdaptedSoltEnums;
import com.irdstudio.efp.nls.service.facade.NlsApplyInfoService;
import com.irdstudio.efp.nls.service.facade.ed.LimitControlsService;
import com.irdstudio.efp.nls.service.facade.queue.NlsProcessRuleService;
import com.irdstudio.efp.nls.service.vo.NlsApplyInfoVO;
import com.irdstudio.efp.nls.service.vo.queue.NlsProcessBizVO;
import com.irdstudio.efp.nls.service.vo.queue.NlsProcessRuleVO;
import com.irdstudio.efp.rule.common.enumeration.RefuseType;
import com.irdstudio.efp.rule.common.enumeration.Rule;
import com.irdstudio.efp.rule.service.facade.RuleCallService;
import com.irdstudio.efp.rule.service.vo.ReqAccessRuleVo;
import com.irdstudio.efp.rule.service.vo.ReqRuleVo;
import com.irdstudio.efp.rule.service.vo.RespRuleVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: 准入规则校验 一 根据申请信息与产品相关要素进行校验<br>
 *               1. 通过申请流水号查询申请信息（nls_apply_info）<br>
 *               2. 根据申请信息中的产品编号查询对应产品信息（prd_info）<br>
 *               3. 将规则所需信息装入规则VO中<br>
 *               二 行员关联人核查<br>
 *               三 黑名单核查<br>
 *               20200520 tiankg 修改：规则迁移需求，去掉反洗钱、行员和关联人核查、名单系统、黑名单、客户限额、年龄限制规则
 * @param appNo
 * @date:2018年12月25日 上午9:06:55
 * @author:hengyh
 */
@Service("accessRuleService")
public class AccessRuleServiceImpl extends SoltServiceImpl {

	private static final Logger log = LoggerFactory.getLogger(AccessRuleServiceImpl.class);

//	@Override
//	public void doExecute(NlsProcessBizVO nlsProcessBizVo,NlsApplyInfoVO nlsApplyInfoVO) throws Exception {
//		String applySeq = nlsProcessBizVo.getApplySeq();
//		String slotCode = nlsProcessBizVo.getSoltCode();
//		String certType = nlsApplyInfoVO.getCertType();
//		String certCode = nlsApplyInfoVO.getCertCode();
//		try {
//			/**
//			 * 马上新增需求——白名单试单
//			 * @author qiuyf
//			 * @date 2019/04/12
//			 */
//			// 根据配置主键、参数值，查参数配置表
//			SCfgParamVO sCfgParamVO = new SCfgParamVO();
//			sCfgParamVO.setParamKey(ConsoleEnums.ParamKey.MS_TRIAL_ORDER_SWITCH.getValue());
//			sCfgParamVO.setParamValue(BaseConstant.YES_Y);
//			sCfgParamVO = sCfgParamService.queryByCondition(sCfgParamVO);
//			if(Objects.nonNull(sCfgParamVO)) {
//				CusWhiteListTecVO cusWhiteListTecVO = new CusWhiteListTecVO();
//				cusWhiteListTecVO.setCertType(certType);
//				cusWhiteListTecVO.setCertNo(certCode);
//				cusWhiteListTecVO = cusWhiteListTecService.queryByCertNoAndTyp(cusWhiteListTecVO);
//
//				if(Objects.isNull(cusWhiteListTecVO)) {
//					nlsProcessBizVo.setRefuseMsg(RefuseType.NOTWHITE_LIST.getMsg());
//					throw new BizException("证件号码为： " + certCode + "的客户不存在白名单中，进件申请失败！");
//				}
//			}
//
//			/**
//			 * 马上新增需求——反洗钱名单校验
//			 * @author qiuyf
//			 * @date 2019/06/25
//			 */
//			NlsQueueSoltComnService nlsQueueSoltComnService = (NlsQueueSoltComnService) SpringContextUtils.getBean("nlsQueueSoltComnService");
//			boolean isGreyBlackList = nlsQueueSoltComnService.isGreyBlackList(certType, certCode);
//			if(isGreyBlackList){
//				nlsProcessBizVo.setRefuseMsg(RefuseType.ISGREY_LIST.getMsg());
//				throw new BizException("证件号码为： " + certCode + "命中反洗钱名单，进件申请失败！");
//			}
//			/** 产品校验 **/
//			log.info("开始进行准入规则产品校验,流水号:" + applySeq);
//			Objects.requireNonNull(nlsApplyInfoVO);
//
//			String prdId = Objects.requireNonNull(nlsApplyInfoVO.getPrdId());
//			PrdInfoVO prdInfoVo = new PrdInfoVO();
//			prdInfoVo.setPrdId(prdId);
//			prdInfoVo = prdInfoService.queryByPk(prdInfoVo);
//
//			// 判断产品生效失效逻辑
////			String defaultEndDate = "2099-01-01";
////			LocalDate startDate = LocalDate.parse(prdInfoVo.getEffictiveDate(), DateTimeFormatter.ISO_DATE);
////			LocalDate endDate = LocalDate.parse(Optional.ofNullable(prdInfoVo.getExpiryDate()).orElse(defaultEndDate), DateTimeFormatter.ISO_DATE);
////			LocalDate now = LocalDate.now();
////			if (startDate.isAfter(now) || endDate.isBefore(now)) {
////				throw new BizException("产品： " + prdInfoVo.getPrdName() + " 不是有效状态");
////			}
//			PrdStatEnums prdStat = PrdStatEnums.parse(prdInfoVo.getPrdStatus());
//			if (!Objects.equals(prdStat, PrdStatEnums.IN_USE)) {
//				nlsProcessBizVo.setRefuseMsg(RefuseType.OTHER.getMsg());
//				throw new BizException("产品： " + prdInfoVo.getPrdName() + " 不是有效状态");
//			}
//			/**额度管控 查询客户限额表 modify by chenxuan*/
//			BigDecimal availAmt = limitControlsService.getAvailAmt(nlsApplyInfoVO);
//			/**额度管控 审批中贷款判断 modify by ludayong*/
//			boolean isDuring = limitControlsService.isDuring(nlsApplyInfoVO);
//
//			/** 初始化规则过程表 */
//			NlsProcessRuleVO nlsProcessRuleVO = new NlsProcessRuleVO();
//			nlsProcessRuleVO.setApplySeq(applySeq);
//			nlsProcessRuleVO.setCreateTime(DateUtility.getCurrDateTime());
//			nlsProcessRuleVO.setLastModifyTime(DateUtility.getCurrDateTime());
//			nlsProcessRuleVO.setPrdCode(prdId);
//			nlsProcessRuleVO.setPrdName(nlsApplyInfoVO.getPrdName());
//			nlsProcessRuleVO.setCusName(nlsApplyInfoVO.getCusName());
//			nlsProcessRuleVO.setCusId(nlsApplyInfoVO.getCusId());
//
//			/** 添加要执行的规则 */
//			List<PrdSoltRuleVO> prdSoltRules = prdSoltRuleService.queryByPrdIdAndSoltCode(prdId, slotCode);
//
//			// 贷款金额
//			BigDecimal applyAmt = nlsApplyInfoVO.getApplyAmt();
//			BigDecimal maxAmt = prdInfoVo.getLoanAppMaxAmt();
//			BigDecimal minAmt = prdInfoVo.getLoanAppMinAmt();
//			// 此次申请贷款期限
//			TermType appTermType = TermType.valueOf(nlsApplyInfoVO.getLoanTermType());
//			TermType stdTermType = TermType.valueOf(prdInfoVo.getLmtTermUnit());
//			int appLoanTerm = appTermType.toDay(Integer.valueOf(nlsApplyInfoVO.getLoanTerm())); // 此次申请贷款期限(转换为天)
//			int minTerm = stdTermType.toDay(Integer.parseInt(prdInfoVo.getMinLoanTerm())); // 产品配置表中的产品最小期限(转换为天)
//			int maxTerm = stdTermType.toDay(Integer.parseInt(prdInfoVo.getMaxLoanTerm())); // 产品配置表中的产品最大期限(转换为天)
//			// 该客户该产品总余额
//			AccLoanVO accLoanVO = new AccLoanVO();
//			accLoanVO.setPrdId(prdId);
//			accLoanVO.setCertType(nlsApplyInfoVO.getCertType());
//			accLoanVO.setCertCode(nlsApplyInfoVO.getCertCode());
//			List<AccLoanVO> accLoanVOs = Optional.ofNullable(accLoanService.queryAccLoanListByCondition(accLoanVO)).orElseGet(Collections::emptyList);
//			BigDecimal totalAmt = accLoanVOs.stream().filter(vo -> {
//				String accStatus = vo.getAccountStatus();
//				return accStatus != null/* && !accStatus.equals(LoanConstant.TZZT_WQR) && !accStatus.equals(LoanConstant.TZZT_JQ) && !accStatus.equals(LoanConstant.TZZT_XH)
//						&& !accStatus.equals(LoanConstant.TZZT_HX) && !accStatus.equals(LoanConstant.TZZT_LPJQ)*/;
//			}).map(AccLoanVO::getLoanBalance).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
//			// 根据审批状态分组
//			NlsApplyInfoVO nlsApplyCode = new NlsApplyInfoVO();
//			nlsApplyCode.setCertCode(nlsApplyInfoVO.getCertCode());
//			Map<String, List<NlsApplyInfoVO>> groupMap = Optional.ofNullable(nlsApplyInfoService.queryCertCode(nlsApplyCode))
//					.orElseGet(Collections::emptyList).stream().filter(i -> !applySeq.equals(i.getApplySeq()))
//					.filter(i -> i.getPrdId().equals(prdId))
//					.collect(Collectors.groupingBy(NlsApplyInfoVO::getNlsApplyState));
//			log.info("获取审批中的--申请金额");
//			// 获取审批中的--申请金额
//			totalAmt = Optional.ofNullable(groupMap.get(MsLoanConstant.NlsApplyStateEnum.APPR.VALUE)).orElseGet(ArrayList::new)
//					.stream().map(NlsApplyInfoVO::getApplyAmt).filter(Objects::nonNull)
//					.reduce(totalAmt, BigDecimal::add);
//			log.info("获取审批通过,待放款--申请金额");
//			// 获取审批通过,待放款--申请金额
//			totalAmt = Optional.ofNullable(groupMap.get(MsLoanConstant.NlsApplyStateEnum.PASS.VALUE)).orElseGet(ArrayList::new)
//					.stream().filter(i -> i.getDnSts() != null && i.getDnSts().equals(BaseConstant.DN_STS_3))
//					.map(NlsApplyInfoVO::getApplyAmt).filter(Objects::nonNull)
//					.reduce(totalAmt, BigDecimal::add);
//			// 获取当前进件申请金额
//			totalAmt = applyAmt.add(totalAmt);
//			/** 行员关联人核查 **/
//			int bankerHitsNum = 0;
//			CusRelCheckVO cusRelCheckVO = cusRelCheckService.queryCusRelCheckBycertCode
//							(MD5Util.getMD5ofStr(nlsApplyInfoVO.getCertCode()).toUpperCase()
//							, nlsApplyInfoVO.getCertType());
//			if (cusRelCheckVO != null
//				&& Objects.equals(RELATION_BANKER, cusRelCheckVO.getRelRelation())
//				&& Objects.equals(cusRelCheckVO.getSts(), ON_WORK)) {
//				bankerHitsNum = 1;
//			}
//			int relationHitsNum = 0;
//			cusRelCheckVO = cusRelCheckService.queryCusRelCheckBycertCode
//					(nlsApplyInfoVO.getCertCode()
//							, nlsApplyInfoVO.getCertType());
//			if (cusRelCheckVO != null
//					&& Objects.equals(RELATION_ASSOCIATE, cusRelCheckVO.getRelRelation())) {
//				relationHitsNum = 1;
//			}
//
//            /* 名单系统校验 */
//            // 马上不查关联人信息
//            NLMHitQueryReports hitQueryReports = NLMHitQueryReports.builder()
//                    // 	客户中文名称
//                    .custCnnm(nlsApplyInfoVO.getCusName())
//                    // 	证件类型
//                    .identTp(nlsApplyInfoVO.getCertType())
//                    // 	证件号码
//                    .identNo(nlsApplyInfoVO.getCertCode())
//					// 境内外标志：默认境内
//					.dmstFrgnFlg("1")
//					// 客户类型：默认个人
//					.custTp("01")
//                    .build();
//			NLMHitQueryResponseReports zx11008Content = null;
//			boolean isConnected = true;
//			try {
//				zx11008Content = zx11008Service.service(hitQueryReports);
//			} catch (Exception e) {
//				log.error(e.getMessage());
//				log.error("调用名单系统异常", e);
//				isConnected = false;
//			}
//			if (isConnected){
//				log.info("名单系统规则参数准备,流水号：" + applySeq + ",查询名单系统接口完成");
//				Objects.requireNonNull(zx11008Content);
//				// Y：命中黑名单，提示类不拒绝
//				if ("Y".equals(zx11008Content.getBlklistCustFlg())) {
//					log.info("命中名单类型信息：{}", zx11008Content.getHitInf());
//					if ("PRMT".equals(zx11008Content.getHitInf())){
//						// 不阻断流程
//						log.warn("命中提示类黑名单，证件号码为{}",certCode);
//					}else {
//						String msg = String.format("命中黑名单,类型：%s,证件号码为：%s,提示信息：%s,超链接：%s",
//								zx11008Content.getHitInf(), certCode, zx11008Content.getSugstMsg(), zx11008Content.getHyprlnksAddr());
//						// refuse_cause 字段最大长度为500
//						int maxLen = 500;
//						if (StringUtils.isNotBlank(msg) && msg.length() > maxLen) {
//							msg = msg.substring(0, maxLen - 4) + "...";
//						}
//						nlsProcessBizVo.setRefuseMsg("证件号码为： " + certCode + "命中开户交易名单，进件申请失败！");
//						throw new BizException(msg);
//					}
//				}
//			}
//
//
//			/** 黑名单 **/
//			int blackListNum = 0;
//			String pbocCertTp = "0";
//			ZX11001QueryReports zx11001QueryReports = new ZX11001QueryReports.Builder().withName(nlsApplyInfoVO.getCusName()).withCertNo(nlsApplyInfoVO.getCertCode()).withCertType(pbocCertTp) // 征信的证件类型-身份证（目前只支持身份证）
//					.build();
//			try {
//				ZXVO zxvo = zx11001Service.service(zx11001QueryReports, prdInfoVo.getZxOpId());
//
//				log.info("准入规则参数准备,流水号：" + applySeq + ",查询黑名单接口完成");
//				@SuppressWarnings("unchecked")
//				ZX11001ResponseReport content = ((List<ZX11001ResponseReport>) zxvo.getResp()).get(0);
//				Objects.requireNonNull(content);
//				Supplier<Integer> zero = () -> Integer.valueOf(0);
//
//				// 黑名单命中次数
//				blackListNum = Stream.of(content.getBankPushBlklistArry(), content.getHghCrtExecPrsnLstArry(), content.getHghCrtLsCrdblPrsnLstArry(), content.getOwnFraudBlklistArry(),
//						content.getOwnSzRskIndBlklistArry(), content.getP2PLsCrdblPrsnLstArry(), content.getOwnRskCardIndBlklistArry(), content.getAbnTxBlklistArry(),
//						content.getLoanRskIndBlklistArry(), content.getIndvBlklistInfArry(), content.getSmhldBlkshlistInfArry(), content.getPBCPblcInfBadBlklistArry(),
//						content.getConsmFinBsnCustBlklistArry()).map(Optional::ofNullable).map(i -> i.map(List::size).orElseGet(zero)).reduce(0, Integer::sum);
//
//			} catch (Exception e) {
//				log.error(e.getMessage());
//				throw new HangException("调用黑名单异常", e);
//			}
//			/** 年龄限制 **/
//			int age = ValidationUtils.getAgeFromIdNumber(nlsApplyInfoVO.getCertCode(),BaseConstant.MS_AGE_START_22,BaseConstant.MS_AGE_END_55);
//			boolean isFemale = ValidationUtils.isFemale(nlsApplyInfoVO.getCertCode());
//			if(isFemale){
//				age = ValidationUtils.getAgeFromIdNumber(nlsApplyInfoVO.getCertCode(),BaseConstant.MS_AGE_START_22,BaseConstant.MS_AGE_END_50);
//			}
//			/** 执行规则 **/
//			log.info("准入规则参数准备,流水号：" + applySeq + ",开始执行准入规则");
//			ReqRuleVo reqRuleVo = new ReqRuleVo();
//			reqRuleVo.setAppNo(applySeq);
//			reqRuleVo.setPrdName(nlsApplyInfoVO.getPrdName());
//			ReqAccessRuleVo param = new ReqAccessRuleVo();
//			param.setBlackListNum(blackListNum);
//			param.setBankerHitsNum(bankerHitsNum);
//			param.setRelatedHitsNum(relationHitsNum);
//			param.setAge(age);
//			param.setFemale(isFemale);
//			param.setMaxLoanAmt(maxAmt);
//			param.setMinLoanAmt(minAmt);
//			param.setLoanAmt(applyAmt);
//			param.setCusLoanBal(totalAmt);
//			param.setMaxLoanBal(prdInfoVo.getLoanMaxAmtBalance());
//			param.setMinTermDay(minTerm);
//			param.setMaxTermDay(maxTerm);
//			param.setAvailAmt(availAmt); // 可用额度
//			param.setDuring(isDuring);// 是否在途
//			param.setAppTermDay(appLoanTerm);
//			reqRuleVo.setReqAccessRuleVo(param);
//
//			/**批量执行规则**/
//			List<RespRuleVO> list = ruleService.executeBatchRule(Rule.RuleType.ACCESS, reqRuleVo);
//			/**规则结果分组**/
//			Map<String, List<RespRuleVO>> map = list.stream().collect(Collectors.groupingBy(RespRuleVO::getRuleId));
//			/** 规则结果信息  反馈给开放平台*/
//			String refuseMsg = "";
//			/** 规则结果信息  记录拒绝原因细类*/
//			StringBuilder sb = new StringBuilder();
//			for (int j = 0; j < prdSoltRules.size(); j++) {
//				String order = prdSoltRules.get(j).getRuleOrder();
//				/** 规则名称method映射 */
//				Method methodRuleName = NlsProcessRuleVO.class.getMethod("setRuleName" + order, String.class);
//				/** 规则状态method映射 */
//				Method methodRuleState = NlsProcessRuleVO.class.getMethod("setRuleState" + order, String.class);
//				/** 规则时间method映射 */
//				Method methodRuleTime = NlsProcessRuleVO.class.getMethod("setRuleTime" + order, String.class);
//
//				methodRuleName.invoke(nlsProcessRuleVO, prdSoltRules.get(j).getRuleCode());
//				methodRuleTime.invoke(nlsProcessRuleVO, DateUtility.getCurrAppDateTimeString());
//				if (map.get(prdSoltRules.get(j).getRuleCode()) != null) {
//					methodRuleState.invoke(nlsProcessRuleVO, PrdAdaptedSoltEnums.SoltProcessStateEnum.FAILURE.getCode());
//					sb.append(prdSoltRules.get(j).getRuleName()).append("规则不通过;");
//					/**根据规则id映射返回开放平台错误信息**/
//					refuseMsg = Rule.parseWithRuleId(prdSoltRules.get(j).getRuleCode()).getMsg();
//				} else {
//					methodRuleState.invoke(nlsProcessRuleVO, PrdAdaptedSoltEnums.SoltProcessStateEnum.SUCCESS.getCode());
//				}
//			}
//			/**设置返回开放平台错误信息**/
//			nlsProcessBizVo.setRefuseMsg(refuseMsg);
//			/** 插入规则过程表 */
//			nlsProcessRuleService.insertNlsProcessRule(nlsProcessRuleVO);
//
//			if (!list.isEmpty()) {
//				throw new BizException(sb.toString());
//			}
//		} catch (Exception e) {
//			log.error(Arrays.toString(e.getStackTrace()));
//			nlsProcessBizVo.setExceptionFlag(true);
//			nlsProcessBizVo.setExceptionMsg(e);
//		}
//	}

    @Override
    public void doExecute(NlsProcessBizVO nlsProcessBizVo,NlsApplyInfoVO nlsApplyInfoVO) throws Exception {
        String applySeq = nlsProcessBizVo.getApplySeq();
        String slotCode = nlsProcessBizVo.getSoltCode();
        String certType = nlsApplyInfoVO.getCertType();
        String certCode = nlsApplyInfoVO.getCertCode();
        try {
            /**
             * 马上新增需求——白名单试单
             * @author qiuyf
             * @date 2019/04/12
             */
            // 根据配置主键、参数值，查参数配置表
            SCfgParamVO sCfgParamVO = new SCfgParamVO();
            sCfgParamVO.setParamKey(ConsoleEnums.ParamKey.MS_TRIAL_ORDER_SWITCH.getValue());
            sCfgParamVO.setParamValue(BaseConstant.YES_Y);
            sCfgParamVO = sCfgParamService.queryByCondition(sCfgParamVO);
            if(Objects.nonNull(sCfgParamVO)) {
                CusWhiteListTecVO cusWhiteListTecVO = new CusWhiteListTecVO();
                cusWhiteListTecVO.setCertType(certType);
                cusWhiteListTecVO.setCertNo(certCode);
                cusWhiteListTecVO = cusWhiteListTecService.queryByCertNoAndTyp(cusWhiteListTecVO);

                if(Objects.isNull(cusWhiteListTecVO)) {
                    nlsProcessBizVo.setRefuseMsg(RefuseType.NOTWHITE_LIST.getMsg());
                    throw new BizException("证件号码为： " + certCode + "的客户不存在白名单中，进件申请失败！");
                }
            }

            /** 产品校验 **/
            log.info("开始进行准入规则产品校验,流水号:" + applySeq);
            Objects.requireNonNull(nlsApplyInfoVO);

            String prdId = Objects.requireNonNull(nlsApplyInfoVO.getPrdId());
            PrdInfoVO prdInfoVo = new PrdInfoVO();
            prdInfoVo.setPrdId(prdId);
            prdInfoVo = prdInfoService.queryByPk(prdInfoVo);
            PrdStatEnums prdStat = PrdStatEnums.parse(prdInfoVo.getPrdStatus());
            if (!Objects.equals(prdStat, PrdStatEnums.IN_USE)) {
                nlsProcessBizVo.setRefuseMsg(RefuseType.OTHER.getMsg());
                throw new BizException("产品： " + prdInfoVo.getPrdName() + " 不是有效状态");
            }

            /**额度管控 审批中贷款判断 modify by ludayong*/
            boolean isDuring = limitControlsService.isDuring(nlsApplyInfoVO);

            /** 初始化规则过程表 */
            NlsProcessRuleVO nlsProcessRuleVO = new NlsProcessRuleVO();
            nlsProcessRuleVO.setApplySeq(applySeq);
            nlsProcessRuleVO.setCreateTime(DateUtility.getCurrDateTime());
            nlsProcessRuleVO.setLastModifyTime(DateUtility.getCurrDateTime());
            nlsProcessRuleVO.setPrdCode(prdId);
            nlsProcessRuleVO.setPrdName(nlsApplyInfoVO.getPrdName());
            nlsProcessRuleVO.setCusName(nlsApplyInfoVO.getCusName());
            nlsProcessRuleVO.setCusId(nlsApplyInfoVO.getCusId());

            /** 添加要执行的规则 */
            List<PrdSoltRuleVO> prdSoltRules = prdSoltRuleService.queryByPrdIdAndSoltCode(prdId, slotCode);

            // 贷款金额
            BigDecimal applyAmt = nlsApplyInfoVO.getApplyAmt();
            BigDecimal maxAmt = prdInfoVo.getLoanAppMaxAmt();
            BigDecimal minAmt = prdInfoVo.getLoanAppMinAmt();
            // 此次申请贷款期限
            TermType appTermType = TermType.valueOf(nlsApplyInfoVO.getLoanTermType());
            TermType stdTermType = TermType.valueOf(prdInfoVo.getLmtTermUnit());
            int appLoanTerm = appTermType.toDay(Integer.valueOf(nlsApplyInfoVO.getLoanTerm())); // 此次申请贷款期限(转换为天)
            int minTerm = stdTermType.toDay(Integer.parseInt(prdInfoVo.getMinLoanTerm())); // 产品配置表中的产品最小期限(转换为天)
            int maxTerm = stdTermType.toDay(Integer.parseInt(prdInfoVo.getMaxLoanTerm())); // 产品配置表中的产品最大期限(转换为天)
            // 该客户该产品总余额
            AccLoanVO accLoanVO = new AccLoanVO();
            accLoanVO.setPrdId(prdId);
            accLoanVO.setCertType(nlsApplyInfoVO.getCertType());
            accLoanVO.setCertCode(nlsApplyInfoVO.getCertCode());
            List<AccLoanVO> accLoanVOs = Optional.ofNullable(accLoanService.queryAccLoanListByCondition(accLoanVO)).orElseGet(Collections::emptyList);
            BigDecimal totalAmt = accLoanVOs.stream().filter(vo -> {
                String accStatus = vo.getAccountStatus();
                return accStatus != null/* && !accStatus.equals(LoanConstant.TZZT_WQR) && !accStatus.equals(LoanConstant.TZZT_JQ) && !accStatus.equals(LoanConstant.TZZT_XH)
						&& !accStatus.equals(LoanConstant.TZZT_HX) && !accStatus.equals(LoanConstant.TZZT_LPJQ)*/;
            }).map(AccLoanVO::getLoanBalance).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 根据审批状态分组
            NlsApplyInfoVO nlsApplyCode = new NlsApplyInfoVO();
            nlsApplyCode.setCertCode(nlsApplyInfoVO.getCertCode());
            Map<String, List<NlsApplyInfoVO>> groupMap = Optional.ofNullable(nlsApplyInfoService.queryCertCode(nlsApplyCode))
                    .orElseGet(Collections::emptyList).stream().filter(i -> !applySeq.equals(i.getApplySeq()))
                    .filter(i -> i.getPrdId().equals(prdId))
                    .collect(Collectors.groupingBy(NlsApplyInfoVO::getNlsApplyState));
            log.info("获取审批中的--申请金额");
            // 获取审批中的--申请金额
            totalAmt = Optional.ofNullable(groupMap.get(MsLoanConstant.NlsApplyStateEnum.APPR.VALUE)).orElseGet(ArrayList::new)
                    .stream().map(NlsApplyInfoVO::getApplyAmt).filter(Objects::nonNull)
                    .reduce(totalAmt, BigDecimal::add);
            log.info("获取审批通过,待放款--申请金额");
            // 获取审批通过,待放款--申请金额
            totalAmt = Optional.ofNullable(groupMap.get(MsLoanConstant.NlsApplyStateEnum.PASS.VALUE)).orElseGet(ArrayList::new)
                    .stream().filter(i -> i.getDnSts() != null && i.getDnSts().equals(BaseConstant.DN_STS_3))
                    .map(NlsApplyInfoVO::getApplyAmt).filter(Objects::nonNull)
                    .reduce(totalAmt, BigDecimal::add);
            // 获取当前进件申请金额
            totalAmt = applyAmt.add(totalAmt);

            /** 执行规则 **/
            log.info("准入规则参数准备,流水号：" + applySeq + ",开始执行准入规则");
            ReqRuleVo reqRuleVo = new ReqRuleVo();
            reqRuleVo.setAppNo(applySeq);
            reqRuleVo.setPrdName(nlsApplyInfoVO.getPrdName());
            ReqAccessRuleVo param = new ReqAccessRuleVo();
            param.setMaxLoanAmt(maxAmt);
            param.setMinLoanAmt(minAmt);
            param.setLoanAmt(applyAmt);
            param.setCusLoanBal(totalAmt);
            param.setMaxLoanBal(prdInfoVo.getLoanMaxAmtBalance());
            param.setMinTermDay(minTerm);
            param.setMaxTermDay(maxTerm);
            param.setDuring(isDuring);// 是否在途
            param.setAppTermDay(appLoanTerm);
            reqRuleVo.setReqAccessRuleVo(param);

            /**批量执行规则**/
            List<RespRuleVO> list = ruleService.executeBatchRule(Rule.RuleType.ACCESS, reqRuleVo);
            /**规则结果分组**/
            Map<String, List<RespRuleVO>> map = list.stream().collect(Collectors.groupingBy(RespRuleVO::getRuleId));
            /** 规则结果信息  反馈给开放平台*/
            String refuseMsg = "";
            /** 规则结果信息  记录拒绝原因细类*/
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < prdSoltRules.size(); j++) {
                String order = prdSoltRules.get(j).getRuleOrder();
                /** 规则名称method映射 */
                Method methodRuleName = NlsProcessRuleVO.class.getMethod("setRuleName" + order, String.class);
                /** 规则状态method映射 */
                Method methodRuleState = NlsProcessRuleVO.class.getMethod("setRuleState" + order, String.class);
                /** 规则时间method映射 */
                Method methodRuleTime = NlsProcessRuleVO.class.getMethod("setRuleTime" + order, String.class);

                methodRuleName.invoke(nlsProcessRuleVO, prdSoltRules.get(j).getRuleCode());
                methodRuleTime.invoke(nlsProcessRuleVO, DateUtility.getCurrAppDateTimeString());
                if (map.get(prdSoltRules.get(j).getRuleCode()) != null) {
                    methodRuleState.invoke(nlsProcessRuleVO, PrdAdaptedSoltEnums.SoltProcessStateEnum.FAILURE.getCode());
                    sb.append(prdSoltRules.get(j).getRuleName()).append("规则不通过;");
                    /**根据规则id映射返回开放平台错误信息**/
                    refuseMsg = Rule.parseWithRuleId(prdSoltRules.get(j).getRuleCode()).getMsg();
                } else {
                    methodRuleState.invoke(nlsProcessRuleVO, PrdAdaptedSoltEnums.SoltProcessStateEnum.SUCCESS.getCode());
                }
            }
            /**设置返回开放平台错误信息**/
            nlsProcessBizVo.setRefuseMsg(refuseMsg);
            /** 插入规则过程表 */
            nlsProcessRuleService.insertNlsProcessRule(nlsProcessRuleVO);

            if (!list.isEmpty()) {//准入规则不通过
                throw new BizException(sb.toString());
            }

        } catch (Exception e) {
            log.error(Arrays.toString(e.getStackTrace()));
            nlsProcessBizVo.setExceptionFlag(true);
            nlsProcessBizVo.setExceptionMsg(e);
        }
    }

	@Autowired
	@Qualifier("nlsApplyInfoService")
	private NlsApplyInfoService nlsApplyInfoService;
	@Autowired
	@Qualifier("prdInfoService")
	private PrdInfoService prdInfoService;
	@Autowired
	@Qualifier("ruleCallService")
	private RuleCallService ruleService;
	@Autowired
	@Qualifier("nlsProcessRuleService")
	private NlsProcessRuleService nlsProcessRuleService;
	@Autowired
	@Qualifier("prdSoltRuleService")
	private PrdSoltRuleService prdSoltRuleService;
	@Autowired
	@Qualifier("accLoanService")
	private AccLoanService accLoanService;
	@Autowired
	@Qualifier("sCfgParamService")
	private SCfgParamService sCfgParamService;
	@Autowired
	@Qualifier("cusWhiteListTecService")
	private CusWhiteListTecService cusWhiteListTecService;
	@Autowired
	@Qualifier("limitControlsService")
	private LimitControlsService limitControlsService;// 已占用额度
    @Autowired
    @Qualifier("msLoanService")
    private MsLoanService msLoanService;//回调通知服务
    @Autowired
    @Qualifier("producerService")
    private MQProducerMessageClient producerService;//发送消息队列
    /*
	@Autowired
	@Qualifier("nlsProcessBizService")
	private NlsProcessBizService nlsProcessBizService;
	@Autowired
	@Qualifier("zx11001Service")
	private ZXService<ZX11001QueryReports> zx11001Service;
	@Autowired
	@Qualifier("zx11008Service")
	private EsbService<NLMHitQueryReports,NLMHitQueryResponseReports> zx11008Service;
	@Autowired
	@Qualifier("ctrLoanContService")
	private CtrLoanContService ctrLoanContService;
	@Autowired
	@Qualifier("cusRelCheckService")
	private CusRelCheckService cusRelCheckService;
	@Autowired
	@Qualifier("cusIndivRelService")
	private CusIndivRelService cusIndivRelService;
    */
	enum TermType {
		Y {
			int toDay(int term) {
				return 365 * term;
			}
		},
		M {
			int toDay(int term) {
				return 12 * term;
			}
		},
		D {
			int toDay(int term) {
				return term;
			}
		};

		abstract int toDay(int term);
	}
/*
	private NLMHitQueryReports.RltdPrsnInfArry rltdPrsnInfArryConverter(CusIndivRelVO cusIndivRelVO) {
		return NLMHitQueryReports.RltdPrsnInfArry.builder()
				// 	关系类型
				.relaTp(cusIndivRelVO.getRelation())
				// 	关联客户名称
				.lnkCustNm(cusIndivRelVO.getRelName())
				// 	关联人证件类型
				.rltvPrsnIdentTp(cusIndivRelVO.getCertType())
				// 	关联人证件号
				.rltvPrsnIdentNo(cusIndivRelVO.getCertCode())
				// 	关联人国籍
//					.rltvPrsnNation()
				.build();
	}*/
    /*
	private static final String RELATION_BANKER = "01"; // 关联关系，行员
	private static final String RELATION_ASSOCIATE = "02"; // 关联关系，关联人
	private static final String ON_WORK = "0"; // 关联人核查--在职
    */
}
